# frozen_string_literal: true

require "rails"
require "active_support/all"
require "decidim/core"
require "decidim/initiatives/content_blocks/registry_manager"
require "decidim/initiatives/current_locale"
require "decidim/initiatives/initiative_slug"
require "decidim/initiatives/menu"
require "decidim/initiatives/query_extensions"

module Decidim
  module Initiatives
    # Decidim"s Initiatives Rails Engine.
    class Engine < ::Rails::Engine
      isolate_namespace Decidim::Initiatives

      routes do
        scope "/:locale", constraints: { locale: Regexp.union(I18n.available_locales.map(&:to_s)) } do
          get "/initiative_types/search", to: "initiative_types#search", as: :initiative_types_search
          get "/initiative_type_scopes/search", to: "initiatives_type_scopes#search", as: :initiative_type_scopes_search
          get "/initiative_type_signature_types/search", to: "initiatives_type_signature_types#search", as: :initiative_type_signature_types_search

          resources :create_initiative do
            collection do
              get :load_initiative_draft
              get :select_initiative_type
              put :select_initiative_type, to: "create_initiative#store_initiative_type"
              get :fill_data
              put :fill_data, to: "create_initiative#store_data"
              get :promotal_committee
              get :finish
            end
          end

          get "initiatives/:initiative_id", to: redirect { |params, _request|
            initiative = Decidim::Initiative.find(params[:initiative_id])
            initiative ? "/#{params[:locale]}/initiatives/#{initiative.slug}" : "/404"
          }, constraints: { initiative_id: /[0-9]+/ }

          get "/initiatives/:initiative_id/f/:component_id", to: redirect { |params, _request|
            initiative = Decidim::Initiative.find(params[:initiative_id])
            initiative ? "/#{params[:locale]}/initiatives/#{initiative.slug}/f/#{params[:component_id]}" : "/404"
          }, constraints: { initiative_id: /[0-9]+/ }

          resources :initiatives, param: :slug, only: [:index, :show, :edit, :update], path: "initiatives" do
            resources :signatures, controller: "initiative_signatures" do
              collection do
                get :fill_personal_data
                put :fill_personal_data, to: "initiative_signatures#store_personal_data"
                get :sms_phone_number
                put :sms_phone_number, to: "initiative_signatures#store_sms_phone_number"
                get :sms_code
                put :sms_code, to: "initiative_signatures#store_sms_code"
                get :finish
                put :finish, to: "initiative_signatures#store_finish"
              end
            end

            member do
              get :authorization_sign_modal, to: "authorization_sign_modals#show"
              get :authorization_create_modal, to: "authorization_create_modals#show"
              get :print, to: "initiatives#print", as: "print"
              get :send_to_technical_validation, to: "initiatives#send_to_technical_validation"
              delete :discard, to: "initiatives#discard"
            end

            resource :initiative_vote, only: [:create, :destroy]
            resources :committee_requests, only: [:new] do
              collection do
                get :spawn
              end
              member do
                get :approve
                delete :revoke
              end
            end
            resources :versions, only: [:show]
          end

          scope "/initiatives/:initiative_slug/f/:component_id" do
            Decidim.component_manifests.each do |manifest|
              next unless manifest.engine

              constraints CurrentComponent.new(manifest) do
                mount manifest.engine, at: "/", as: "decidim_initiative_#{manifest.name}"
              end
            end
          end
        end

        get "/initiatives", to: redirect { |params, request|
          locale = params[:locale] || request.session[:user_locale] || I18n.locale
          "/#{locale}/initiatives"
        }

        get "/initiatives/*rest", to: redirect { |params, request|
          locale = params[:locale] || request.session[:user_locale] || I18n.locale

          "/#{locale}/initiatives/#{params[:rest]}"
        }

        get "/initiative_types/*rest", to: redirect { |params, request|
          locale = params[:locale] || request.session[:user_locale] || I18n.locale

          "/#{locale}/initiative_types/#{params[:rest]}"
        }

        get "/initiative_type_scopes/*rest", to: redirect { |params, request|
          locale = params[:locale] || request.session[:user_locale] || I18n.locale

          "/#{locale}/initiative_type_scopes/#{params[:rest]}"
        }

        get "/initiative_type_signature_types/*rest", to: redirect { |params, request|
          locale = params[:locale] || request.session[:user_locale] || I18n.locale

          "/#{locale}/initiative_type_signature_types/#{params[:rest]}"
        }
      end

      initializer "decidim_initiatives.mount_routes" do
        Decidim::Core::Engine.routes do
          mount Decidim::Initiatives::Engine, at: "/", as: "decidim_initiatives"
        end
      end

      initializer "decidim_initiatives.register_icons" do
        Decidim.icons.register(name: "Decidim::Initiative", icon: "lightbulb-flash-line", description: "Initiative", category: "activity", engine: :initiatives)
        Decidim.icons.register(name: "apps-line", icon: "apps-line", category: "system", description: "", engine: :initiatives)
        Decidim.icons.register(name: "printer-line", icon: "printer-line", category: "system", description: "", engine: :initiatives)
        Decidim.icons.register(name: "forbid-line", icon: "forbid-line", category: "system", description: "", engine: :initiatives)
      end

      initializer "decidim_initiatives.data_migrate", after: "decidim_core.data_migrate" do
        DataMigrate.configure do |config|
          config.data_migrations_path << root.join("db/data").to_s
        end
      end

      initializer "decidim_initiatives.stats" do
        Decidim.stats.register :initiatives_count,
                               priority: StatsRegistry::HIGH_PRIORITY,
                               icon_name: "lightbulb-flash-line",
                               tooltip_key: "initiatives_count_tooltip" do |organization, _start_at, _end_at|
          Decidim::Initiative.where(organization:).public_spaces.count
        end
      end

      initializer "decidim_initiatives.content_blocks" do
        Decidim::Initiatives::ContentBlocks::RegistryManager.register!
      end

      initializer "decidim_initiatives.add_cells_view_paths" do
        Cell::ViewModel.view_paths << File.expand_path("#{Decidim::Initiatives::Engine.root}/app/cells")
        Cell::ViewModel.view_paths << File.expand_path("#{Decidim::Initiatives::Engine.root}/app/views") # for partials
      end

      initializer "decidim_initiatives.menu" do
        Decidim::Initiatives::Menu.register_menu!
        Decidim::Initiatives::Menu.register_mobile_menu!
        Decidim::Initiatives::Menu.register_home_content_block_menu!
      end

      initializer "decidim_initiatives.badges" do
        Decidim::Gamification.register_badge(:initiatives) do |badge|
          badge.levels = [1, 5, 15, 30, 50]

          badge.valid_for = [:user]

          badge.reset = lambda { |model|
            Decidim::Initiative.where(
              author: model
            ).published.count
          }
        end
      end

      initializer "decidim_initiatives.query_extensions" do
        Decidim::Api::QueryType.include QueryExtensions
      end

      initializer "decidim_initiatives.shakapacker.assets_path" do
        Decidim.register_assets_path File.expand_path("app/packs", root)
      end

      initializer "decidim_initiatives.preview_mailer" do
        # Load in mailer previews for apps to use in development.
        # We need to make sure we call `Preview.all` before requiring our
        # previews, otherwise any previews the app attempts to add need to be
        # manually required.
        if Rails.env.local?
          ActionMailer::Preview.all

          Dir[root.join("spec/mailers/previews/**/*_preview.rb")].each do |file|
            require_dependency file
          end
        end
      end

      initializer "decidim_initiatives.authorization_transfer" do
        config.to_prepare do
          Decidim::AuthorizationTransfer.register(:initiatives) do |transfer|
            transfer.move_records(Decidim::Initiative, :decidim_author_id)
            transfer.move_records(Decidim::InitiativesVote, :decidim_author_id)
          end
        end
      end
    end
  end
end
